package mrusanov.tournament

import mrusanov.team.Team
import java.util.Date

abstract class TournamentRound(clubsCount:Int, reward:TournamentReward) {
  private var _teams:List[Team] = List()
  private[tournament] var _matches:Map[Int, List[MatchInfo]] = Map()

  def initTournamentRound(teams:List[Team]) {
    require(teams.size == clubsCount, "Clubs size is " + teams.size +
      " but expected size is " + clubsCount)
    _teams = teams
    initMatches()
  }

  def initMatches()

  def initialized = _teams.size != 0
  def teams =  _teams
  def resultsForReward:List[Team]

  def matches = _matches
  def passedRound:List[Team]
  def isOver:Boolean = {
    if (!initialized) {
      return false
    }

    _matches.forall(_._2 forall (_.isOver))
  }

  def matchDayOver(matchDay:Int):Boolean = {
    if (!initialized) {
      return false
    }

    matches(matchDay) forall (_.isOver)
  }

  def payReward() {
    require(isOver, "Impossible to pay reward when tournament is not isOver yet!")
    reward.payReward(resultsForReward)
  }

  private[tournament] def getMatches(clubs:List[Team], date:Date, straightHostGuestOrder:Boolean = true) : List[MatchInfo] = {
    val res = for {
      list <- clubs.grouped(2)
    } yield straightHostGuestOrder match {
        case true => new MatchInfo(list(0), list(1), date)
        case false => new MatchInfo(list(1), list(0), date)
    }
    res.toList
  }

  private [tournament] def uniteMatchDays(firstMap:Map[Int, List[MatchInfo]], secondMap:Map[Int, List[MatchInfo]]):Map[Int, List[MatchInfo]] = {
    var retMap:Map[Int, List[MatchInfo]] = Map()
    val tours = Set() ++ firstMap.keys ++ secondMap.keys
    for (i <- tours) {
      retMap += (i -> (getOrEmptyList(i, firstMap) ::: getOrEmptyList(i, secondMap)))
    }

    retMap
  }

  private[this] def getOrEmptyList[T](index:Int, map:Map[Int, List[T]]):List[T] = {
    if (map.contains(index)) {
      map(index)
    } else {
      Nil
    }
  }

  def allMatches = _matches.toList.sortBy(_._1).map(_._2).flatten
  def teamMatches(team:Team) = allMatches.filter(_.tookPart(team))
}
